//@{VER(>=8.0.23)}
//@<> Setup
testutil.deployRawSandbox(__mysql_sandbox_port1, "root");
shell.connect(__sandbox_uri1);
session.runSql('INSTALL COMPONENT "file://component_query_attributes"');

//@<> Set Query Attribute Errors, Empty Dictionary No Previous Call
EXPECT_NO_THROWS(function() {session.setQueryAttributes({});});


//@<> Set Query Attribute Errors
EXPECT_THROWS(function() {session.setQueryAttributes([])}, 'Argument #1 is expected to be a map');

function validate_query_attributes(expected_results) {
    fields = [];
    for(index = 0; index < expected_results.length; index++) {
        fields.push(`mysql_query_attribute_string("at${index+1}") as at${index+1}`);
    }
    let result = session.runSql(`select ${fields.join(", ")}`);
    let data = result.fetchOneObject();
    for(index = 0; index < expected_results.length; index++) {
        let actual = data[`at${index+1}`]
        EXPECT_EQ(expected_results[index], actual, `Comparing at${index+1}, expected ${expected_results[index]}, actual ${actual}`);
    }
}

//@<> Basic query attribute definition
session.setQueryAttributes({at1: 'val1', at2: '', at3: 45, at4: true, at5: false, at6: 45.2, at7: new Date(2022, 6, 22, 15, 35, 30, 100)});
validate_query_attributes(['val1', '', '45', '1', '0', '45.2', '2022-07-22 15:35:30.100000']);


//@<> Query attributes belong only to the next query
validate_query_attributes([null, null, null, null]);


//@<> Calling setQueryAttributes multiple times, last attribute set overrides initial
session.setQueryAttributes({at1: 'val1', at2: 'val2', at3: 'val3', at4: 'val4'});
session.setQueryAttributes({at1: 'val1', at2: 'val2', at3: 'val3'});
validate_query_attributes(['val1', 'val2', 'val3', null]);

//@<> Calling setQueryAttributes without arguments cleans previouly defined attributes
session.setQueryAttributes({at1: 'val1', at2: 'val2', at3: 'val3', at4: 'val4'});
session.setQueryAttributes({});
validate_query_attributes([null, null, null, null]);

//@<> Trying quoted attribute/values
session.setQueryAttributes({"some attribute": "some value"});
let result = session.runSql('select mysql_query_attribute_string("some attribute") as at1');
let data = result.fetchOneObject();
EXPECT_EQ("some value", data["at1"]);


//@<> Query attributes with >32 key value pairs
let attributes = {}
let expected = []
for(i=1; i<=33; i++) {  attributes[`at${i}`]=i; expected.push(null); }
EXPECT_THROWS(function(){session.setQueryAttributes(attributes);}, "The following query attribute exceed the maximum limit (32): at9");
validate_query_attributes(expected)

//@<> Query attribute, long attribute name (1025 chars)
EXPECT_THROWS(function() {session.setQueryAttributes({at1: 'val1', A1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234: 'val2', at3: 'val3'});},"Invalid query attributes found: The following query attribute exceed the maximum name length (1024): A1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234");
let result2 = session.runSql('select mysql_query_attribute_string("at1") as at1, mysql_query_attribute_string("A1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234") as at2, mysql_query_attribute_string("at3") as at3');
let data2 = result2.fetchOneObject()
EXPECT_EQ(null, data2["at1"]);
EXPECT_EQ(null, data2["at2"]);
EXPECT_EQ(null, data2["at3"]);

//@<> Query attribute, long value (1025 chars)
EXPECT_THROWS(function() {session.setQueryAttributes({at1: 'val1', at2: '01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234', at3:'val3'});}, "Invalid query attributes found: The following query attribute exceed the maximum value length (1024): at2");
let result3 = session.runSql('select mysql_query_attribute_string("at1"), mysql_query_attribute_string("at2"), mysql_query_attribute_string("at3")');
let data3 = result3.fetchOneObject()
EXPECT_EQ(null, data2["at1"]);
EXPECT_EQ(null, data2["at2"]);
EXPECT_EQ(null, data2["at3"]);

//@<> Query attribute, unsupported data type
EXPECT_THROWS(function() {session.setQueryAttributes({at1: [1,2,3], at2: {inner1: 1}, at3:function(){}, att4: session});}, "Invalid query attributes found: The following query attributes have an unsupported data type: at1, at2, at3, att4");
validate_query_attributes([null, null, null, null])

//@<> Cleanup
shell.disconnect()
testutil.stopSandbox(__mysql_sandbox_port1, {wait:1})
testutil.destroySandbox(__mysql_sandbox_port1)
